#ifndef _MSTP_TYPES_H
#define _MSTP_TYPES_H

#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
              
#pragma pack(1)

#define CHUNK_HDR_SZ 		sizeof(chunk_hdr_t)
#define MAX_CHUNK_SZ 		1024*16
#define MAX_BUFF_LEN 		1024*1024*6
#define MAX_RECV_BUFF_LEN	(MAX_CHUNK_SZ + CHUNK_HDR_SZ) * 3
#define DEFAULT_MAX_STREAMS	100

#define ATOMIC_SEND  		1024*1024*4
#define ATOMIC_RECV		1024*1024*4

#define STREAM_OPEN		0x01
#define STREAM_CLOSE		0x02

#define PRIVATE static
#define PUBLIC  extern




extern int errno;

typedef unsigned short u_int16_t;
typedef unsigned int   u_int32_t;

typedef struct  {
    u_int32_t chunk_nr;
    u_int16_t chunk_sz;
} chunk_hdr_t;


/*
 *          CACHE
 *
 *	    +---+-----+------+---+     
 * 	 <----* | hdr | data | *---->
 *	    +---+-----+------+---+
 */
typedef struct chunk_cache {

    chunk_hdr_t        hdr;
    u_int8_t           data[MAX_CHUNK_SZ];
    struct chunk_cache *next;
    struct chunk_cache *prev;

} chunk_cache_t;
    
typedef struct {
    u_int32_t buff_sz;	   /* Total size of the buffer */
    u_int32_t bytes_occ;   /* Occupied bytes           */
    u_int32_t bytes_free;  /* Free bytes 	       */
    u_int8_t  *buff_free;  /* Start of the free Zone   */
    u_int8_t  *buff;
} buff_t;


typedef struct stream_queue {
    struct stream *head;
    struct stream *tail;
} stream_queue_t;   

typedef struct stream {
    int socket;

    u_int8_t  status;
        
    u_int32_t bytes_send;
    u_int32_t bytes_recv;
    u_int32_t nr_rdy_s_times;
    u_int32_t nr_rdy_r_times;

    u_int32_t bytes_in_queue;
    buff_t    send_buffer; 
    buff_t    recv_buffer;
    
    struct timeval start_time;
    double average_speed;

    struct stream *p_nextready_send;
    struct stream *p_nextready_recv;

    struct stream *p_next;
} stream_t;    


typedef struct mstp {
    u_int32_t      chunk_seq_send;
    u_int32_t      chunk_seq_recv;
    u_int8_t       nr_streams;
    u_int8_t       max_streams;
    buff_t         io_buffer;

    chunk_cache_t      *heap;
    chunk_cache_t      *send_cache;    
    chunk_cache_t      *recv_cache;
    stream_queue_t     streams;

    struct sockaddr_in addr;
    int udp_socket;
} mstp_t;


PUBLIC int mstp_socket	(mstp_t *mstp_socket);
PUBLIC int mstp_accept	(mstp_t *mstp_socket, int streams);
PUBLIC int mstp_bind	(mstp_t *socket, struct sockaddr_in *addr);
PUBLIC int mstp_connect	(mstp_t *mstp_socket, struct sockaddr_in *addr, struct timeval *timeout);
                    
#endif
